home *** CD-ROM | disk | FTP | other *** search
- README.TXT - Read-me file for SUBCLS.ZIP
-
- ------------------------------------------------------------------------
- NOTE: Use -d when unzipping SUBCLS.ZIP to have subdirectories recreated.
- ------------------------------------------------------------------------
-
- Subclassing Examples, Copyright (c) 1995 Jonathan Wood and Karl Peterson
- Redistributed by Permission
-
-
- INTRODUCTION:
- The accompanying files provide several examples of using a subclassing
- control with Visual Basic to intercept Windows messages. Emphasis is
- placed on those messages that result in functionality that cannot be
- obtained through Visual Basic alone.
-
- These files include complete source code for an article in the September
- 1995 issue of Visual Basic Programmer's Journal (tentatively entitled
- "Subclass your way around VB's limitations"). Refer to that article for
- additional information on the techniques used. Also included here are
- four additional examples not mentioned in the article.
-
- In addition, the subclassing control MSGHOOK.VBX is also included.
- Although other subclassing controls are available, the examples
- presented here are written to work with this control. See MSGHOOK.TXT
- for more information regarding the Message Hook custom control.
-
- If you'd like to contact the authors of the demo programs and article,
- they can be reached on CompuServe in either the VBPJ or MSBASIC forums.
- Jonathan Wood at 72134,263 and Karl Peterson at 72302,3707.
-
-
- EXAMPLES:
- The article contains 8 tips. They are described briefly below and
- reference is made to the project that corresponds to the tip. Following
- these 8 tips are 4 additional ones. Since these were not covered in the
- article, a discussion of them is provided.
-
- 1. SHOWING STATUSBAR INFORMATION FOR MENU COMMANDS
- Refer to the article and the MENUSEL project.
-
- 2. ADDING A COMMAND TO A FORM'S SYSTEM MENU
- Refer to the article and the SYSCMD project.
-
- 3. SUPPORTING DRAG-AND-DROP FROM FILE MANAGER
- Refer to the article and the DROPFILE project.
-
- 4. LEFT JUSTIFYING CAPTION TEXT
- Refer to the article and the LEFTCAP project.
-
- 5. RESTRICTING A WINDOW SIZE RANGE
- Refer to the article and the GETMINMX project.
-
- 6. PAINTING THE BACKGROUND OF AN MDIFORM
- Refer to the article and the MDIPAINT project.
-
- 7. DRAWING CUSTOM MENU COMMANDS
- Refer to the article and the OWNRDRAW project.
-
- 8. HOOKING INTO THE CLIPBOARD VIEWER CHAIN
- Refer to the article and the CLIPVIEW project.
-
-
- 9. CHANGING MENU TEXT (INITMENU)
- Visual Basic allows you to modify the text of a menu command by setting
- the Caption property of a menu object. However, it often makes more
- sense to be able to set this caption just before the drop down menu is
- displayed. For example, let's say you had a spreadsheet with names and,
- when a menu was dropped down, you wanted the currently selected name to
- appear in the menu as part of a command. Rather than changing the menu
- caption every time the current selection changes, wouldn't it be easier
- to simply set the caption to the currently selected name just before the
- menu is displayed?
-
- Visual Basic does allow you to do this. For example, if you have an Edit
- menu that contains a Copy command, you can modify the Copy command's
- Caption property in the Edit menu's Click event. The Edit menu's Click
- event occurs before the menu is displayed. Unfortunately, Windows has
- already calculated the width of the menu at this point. If the new text
- for the caption is longer that the width of the menu, the text will be
- cut off.
-
- We can solve this problem by using a subclassing control to intercept
- the WM_INITMENUPOPUP message. This message is sent before a drop down
- menu is displayed and, significantly, before the width of the menu has
- been calculated. The INITMENU project demonstrates this technique.
-
- The value you assign to the Result parameter, which MsgHook passes to
- the Message event handler, will be returned to Windows. Like the wParam
- and lParam paramters, the meaning of the value returned depends on the
- actual message being sent. However, most messages, including
- WM_MENUSELECT, simply use a return value of 0 to indicate that your
- program processed the message.
-
-
- 10. DETECTING SYSTEM COLOR CHANGES (SYSCOLOR)
- Often when painting custom elements on your forms, you want to use the
- default system colors so they will blend in nicely with the appearance
- of the rest of the screen. Windows offers the GetSysColor API call to
- retrieve any of the colors which the user can set in Control Panel for
- items such as buttons, titlebars, borders, and so on. But, what if the
- user alters their color preferences while your program is running? For
- performance reasons, you may decide that it's best to store the system
- colors in an array, so you can draw immediately with them rather than
- calling the GetSysColor API repeatedly.
-
- Hooking the WM_SYSCOLORCHANGE provides notification whenever the system
- colors change. This message is closely followed with a WM_PAINT message
- which will fire the Form_Paint event in your project. By retrieving each
- of the system colors during the hooked Message event (see the SYSCOLOR
- project), the color array is refreshed prior to the painting. There is
- no need to invoke the original window procedure as Visual Basic has never
- reacted to this message.
-
- One other point of interest is the way the array of colors is initially
- filled. Rather than duplicate the looping code, SendMessage is employed
- to fire the Message event just set up during the Form_Load event.
-
-
- 11. FORCING AN APP TO REMAIN MINIMIZED (MINAPP)
- Some applications don't need a windowed user interface. These are
- typically written to process large quantities of data in the background,
- or to sit idly by monitoring and reacting to system events. If you've
- written such an application, you may decide that itÆs best for it to
- remain minimized either as an icon or in the Windows 95 taskbar, but
- Visual Basic doesn't provide a convenient means of doing so. If a form's
- WindowState is reset to Minimized whenever a Form_Resize event occurs,
- there's still an ugly flash as the form first restores to Normal or
- Maximized.
-
- Hooking the WM_QUERYOPEN message (see the MINAPP project) provides a
- means for your form to be notified before its state is altered. An
- application can notify Windows that the icon may be opened by returning a
- non-zero value, or prevent the icon from opening by returning zero. To
- implement this technique in Visual Basic, simply return zero in the
- Result parameter when the Message event is fired. There is no need to
- invoke the original window procedure.
-
- One precaution to observe is to not perform any actions which would cause
- an activation or alter the focus while processing this message. To
- provide some degree of user interaction with your iconized application,
- implement the code presented in the SYSCMD project to add one or several
- menu options to the form's system menu.
-
-
- 12. PREVENTING A WINDOW FROM BEING SIZED OR MOVED (WINPOSCH)
- Just before a window gets sized or moved, Windows sends it a
- WM_WINDOWPOSCHANGING message that includes information about the new
- window position. A window procedure can inspect the information about the
- new position and even modify it.
-
- The WM_WINDOWPOSCHANGING message uses the lParam parameter to hold the
- address of (or pointer to) a WINDOWPOS user-defined type (see the
- WINPOSCH project). While Visual Basic doesn't support pointers, the
- Windows API provides a function called hmemcpy which can be used to copy
- data from one location to another. Using hmemcpy, this example copies the
- data from the address specified by lParam to a Visual Basic variable of
- type WINDOWPOS. Note that the code declares two hmemcpy parameters As
- Any. This is done to provide maximum flexibility but also means that
- Visual Basic is not able to verify that the correct data types are sent.
- Care should be taken when incorporating hmemcpy in your own applications,
- as it can be a little tricky.
-
- After using hmemcpy, we end up with a copy of the WINDOWPOS data
- structure in a Visual Basic variable. This data structure contains
- information about the new window position. If this information is
- modified, the changes will affect how the window is moved. Setting the
- SWP_NOSIZE and SWP_NOMOVE bits of the flags element of the WINDOWPOS
- structure prevents any moving or sizing at all. This example, sets
- these bits and then calls hmemcpy once again to copy the data structure
- back.
-
- This project contain some additional statements to detect if the window
- is minimized. If the window is minimized, the program allows the window
- to be sized normally. Apparently, when a window gets this message as the
- result of a window becoming unminimized, the form's WindowState will
- already indicate that the form is not an icon. Therefore, the code also
- keeps track of the WindowState for the last time the WM_WINDOWPOSCHANGING
- message was received. If you feel like experimenting, you can take these
- conditional statements out and see how the form behaves when you minimize
- it.
-